#include "networkinfo.h"
#include <QDateTime>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QFile>
#include <QTextStream>
#include <QProcess>
#include <QLocale>
#include <QDebug>
#include <cstdio>
#include <QHostInfo>
#include <QEventLoop>
#include <QPointer>

// 辅助函数：CIDR转子网掩码
static QString cidrToNetmask(const QString &cidrStr) {
    bool ok = false;
    int cidr = cidrStr.toInt(&ok);
    if (!ok || cidr < 0 || cidr > 32) return "";
    quint32 mask = cidr == 0 ? 0 : (~0U << (32 - cidr));
    return QString("%1.%2.%3.%4")
        .arg((mask >> 24) & 0xFF)
        .arg((mask >> 16) & 0xFF)
        .arg((mask >> 8) & 0xFF)
        .arg(mask & 0xFF);
}

// 新增：获取网卡物理型号描述
static QString getPciModelByIface(const QString &iface) {
    QString devicePath = QString("/sys/class/net/%1/device/uevent").arg(iface);
    QFile slotFile(devicePath);
    if (!slotFile.open(QIODevice::ReadOnly | QIODevice::Text))
        return "";
    QString slotName;
    while (!slotFile.atEnd()) {
        QString line = slotFile.readLine();
        if (line.startsWith("PCI_SLOT_NAME=")) {
            slotName = line.section('=', 1).trimmed();
            break;
        }
    }
    slotFile.close();
    if (slotName.isEmpty())
        return "";
    QProcess proc;
    proc.start("lspci", QStringList() << "-s" << slotName);
    proc.waitForFinished();
    QString output = QString::fromUtf8(proc.readAllStandardOutput());
    QStringList parts = output.split(":");
    if (parts.size() > 2)
        return parts[2].trimmed();
    return output.trimmed();
}

NetworkInfo::NetworkInfo(QObject *parent)
    : QObject(parent)
    , m_autoRefreshTimer(new QTimer(this))
    , m_nmcliProcess(new QProcess(this))
    , m_currentCommand(CommandType::None)
{
    // 连接信号槽
    connect(m_autoRefreshTimer, &QTimer::timeout, this, &NetworkInfo::onAutoRefreshTimer);
    connect(m_nmcliProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
            this, &NetworkInfo::onNmcliProcessFinished);
    connect(m_nmcliProcess, &QProcess::errorOccurred, this, &NetworkInfo::onNmcliProcessError);
    
    // 立即获取初始数据
    refreshAll();
    
    // 设置默认自动刷新间隔为5秒
    setAutoRefreshInterval(5000);
}

NetworkInfo::~NetworkInfo()
{
    if (m_nmcliProcess->state() != QProcess::NotRunning) {
        m_nmcliProcess->terminate();
        m_nmcliProcess->waitForFinished(3000);
    }
}

QList<ConnectionInfo> NetworkInfo::getAllConnections()
{
    if (m_cachedConnections.isEmpty()) {
        refreshAll();
    }
    return m_cachedConnections;
}

QList<DeviceInfo> NetworkInfo::getAllDevices()
{
    if (m_cachedDevices.isEmpty()) {
        refreshAll();
    }
    return m_cachedDevices;
}

NetworkStats NetworkInfo::getDeviceStats(const QString &deviceName)
{
    if (!m_cachedStats.contains(deviceName)) {
        // 执行统计信息查询
        m_currentCommand = CommandType::Stats;
        m_currentDevice = deviceName;
        executeNmcliCommand({"device", "show", deviceName});
        
        // 返回默认值，等待异步查询完成
        NetworkStats defaultStats;
        return defaultStats;
    }
    
    NetworkStats stats = m_cachedStats.value(deviceName);
    return stats;
}

void NetworkInfo::forceRefreshDeviceStats(const QString &deviceName)
{
    QProcess *proc = new QProcess(this);
    QStringList args = {"device", "show", deviceName};
    connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
        this, [this, proc, deviceName](int exitCode, QProcess::ExitStatus) {
            QString output = QString::fromUtf8(proc->readAllStandardOutput());
            if (exitCode == 0) {
                NetworkStats stats = parseDeviceStats(output);
                m_cachedStats[deviceName] = stats;
                emit deviceStatsUpdated(deviceName, stats);
            }
            proc->deleteLater();
        });
    proc->start("nmcli", args);
}

QString NetworkInfo::getNetworkStatus()
{
    QString status;
    int connectedCount = 0;
    int totalCount = m_cachedConnections.size();
    
    for (const auto &conn : m_cachedConnections) {
        if (conn.status == ConnectionStatus::Connected) {
            connectedCount++;
        }
    }
    
    if (totalCount == 0) {
        status = "未检测到网络连接";
    } else if (connectedCount == 0) {
        status = "所有网络连接已断开";
    } else if (connectedCount == totalCount) {
        status = QString("所有 %1 个网络连接正常").arg(totalCount);
    } else {
        status = QString("%1/%2 个网络连接正常").arg(connectedCount).arg(totalCount);
    }
    
    return status;
}

void NetworkInfo::refreshAll()
{
    // 先获取设备状态
    QProcess statusProc;
    statusProc.start("nmcli", {"device", "status"});
    statusProc.waitForFinished(2000);
    QString statusOutput = QString::fromUtf8(statusProc.readAllStandardOutput());
    updateDeviceStatusMap(statusOutput);
    // 获取所有设备名
    QStringList devNames;
    QStringList statusLines = statusOutput.split('\n', Qt::SkipEmptyParts);
    for (int i = 1; i < statusLines.size(); ++i) { // 跳过表头
        QString line = statusLines[i].trimmed();
        if (line.isEmpty()) continue;
        QString dev = line.section(' ', 0, 0).trimmed();
        if (!dev.isEmpty()) devNames << dev;
    }
    // 再获取连接列表
    m_currentCommand = CommandType::Connections;
    executeNmcliCommand({"-m", "multiline", "connection", "show"});
    // 不再在此处调用updateInternetConnectivityFromNmcli和updateInternetConnectivity
    // 新增：采集所有设备的device show输出，补全多IP
    QMap<QString, QStringList> devIpMap, devMaskMap;
    QMap<QString, int> devIpOrderMap; // 记录主IP在device show中的索引
    for (const QString &dev : devNames) {
        QProcess devShowProc;
        devShowProc.start("nmcli", {"device", "show", dev});
        devShowProc.waitForFinished(2000);
        QString devShowOut = QString::fromUtf8(devShowProc.readAllStandardOutput());
        QStringList ips, masks;
        for (const QString &dline : devShowOut.split('\n')) {
            QString tline = dline.trimmed();
            if (tline.startsWith("IP4.ADDRESS[")) {
                QString ipInfo = tline.section(':', 1).trimmed();
                QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
                QRegularExpressionMatch match = ipRegex.match(ipInfo);
                if (match.hasMatch()) {
                    ips << match.captured(1);
                    int cidr = match.captured(2).toInt();
                    quint32 mask = (cidr >= 0 && cidr <= 32) ? ((0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF) : 0;
                    QString netmask = QString("%1.%2.%3.%4")
                        .arg((mask >> 24) & 0xFF)
                        .arg((mask >> 16) & 0xFF)
                        .arg((mask >> 8) & 0xFF)
                        .arg(mask & 0xFF);
                    masks << netmask;
                }
            }
        }
        devIpMap[dev] = ips;
        devMaskMap[dev] = masks;
    }
    // 读取connection show的主IP顺序
    QMap<QString, QStringList> connShowIpMap, connShowMaskMap;
    for (const QString &dev : devNames) {
        QProcess connShowProc;
        connShowProc.start("nmcli", {"connection", "show", dev});
        connShowProc.waitForFinished(2000);
        QString connShowOut = QString::fromUtf8(connShowProc.readAllStandardOutput());
        
        for (const QString &line : connShowOut.split('\n')) {
            QString tline = line.trimmed();
            if (tline.startsWith("ipv4.addresses:")) {
                QString addrStr = tline.section(':', 1).trimmed();
                if (!addrStr.isEmpty()) {
                    QStringList addrList = addrStr.split(',', Qt::SkipEmptyParts);
                    QStringList ipList, maskList;
                    for (const QString &addr : addrList) {
                        QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
                        QRegularExpressionMatch match = ipRegex.match(addr.trimmed());
                        if (match.hasMatch()) {
                            ipList << match.captured(1);
                            int cidr = match.captured(2).toInt();
                            quint32 mask = (cidr >= 0 && cidr <= 32) ? ((0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF) : 0;
                            QString netmask = QString("%1.%2.%3.%4")
                                .arg((mask >> 24) & 0xFF)
                                .arg((mask >> 16) & 0xFF)
                                .arg((mask >> 8) & 0xFF)
                                .arg(mask & 0xFF);
                            maskList << netmask;
                        }
                    }
                    connShowIpMap[dev] = ipList;
                    connShowMaskMap[dev] = maskList;
                }
            }
        }
    }
    // 合并到ConnectionInfo，优先用connection show顺序
    for (ConnectionInfo &conn : m_cachedConnections) {
        if (connShowIpMap.contains(conn.device) && !connShowIpMap[conn.device].isEmpty()) {
            conn.ipAddresses = connShowIpMap[conn.device];
            conn.netmasks = connShowMaskMap[conn.device];
        } else if (devIpMap.contains(conn.device)) {
            conn.ipAddresses = devIpMap[conn.device];
            conn.netmasks = devMaskMap[conn.device];
        }
        // 兼容性主IP
        if (!conn.ipAddresses.isEmpty()) {
            conn.ipAddress = conn.ipAddresses[0];
            conn.netmask = conn.netmasks.value(0);
        }
        
        // 更新DHCP信息（从属网卡跳过）
        if (!conn.name.startsWith("bond-slave-")) {
            for (const QString &dev : devNames) {
                if (conn.device == dev) {
                    QProcess dhcpProc;
                    dhcpProc.start("nmcli", {"connection", "show", dev});
                    dhcpProc.waitForFinished(2000);
                    QString dhcpOut = QString::fromUtf8(dhcpProc.readAllStandardOutput());
                    for (const QString &line : dhcpOut.split('\n')) {
                        QString tline = line.trimmed();
                        if (tline.toLower().startsWith("ipv4.method:")) {
                            QString method = tline.section(':', 1).trimmed();
                            conn.ipv4Method = method;
                            conn.dhcp = (method.toLower() == "auto");
                            break;
                        } else if (tline.startsWith("DHCP4.OPTION[")) {
                            conn.dhcp = true;
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }
    for (DeviceInfo &dev : m_cachedDevices) {
        if (devIpMap.contains(dev.name)) {
            dev.ipAddress = devIpMap[dev.name].value(0);
            dev.netmask = devMaskMap[dev.name].value(0);
        }
        if (dev.speed.isEmpty()) {
            QProcess ethtoolProc;
            ethtoolProc.start("ethtool", QStringList() << dev.name);
            if (ethtoolProc.waitForFinished(1000)) {
                QString ethtoolOut = QString::fromUtf8(ethtoolProc.readAllStandardOutput());
                QRegularExpression speedRe("Speed: (\\d+Mb/s)");
                QRegularExpressionMatch match = speedRe.match(ethtoolOut);
                if (match.hasMatch()) {
                    dev.speed = match.captured(1);
                }
            }
        }
    }
}

void NetworkInfo::setAutoRefreshInterval(int interval)
{
    if (interval > 0) {
        m_autoRefreshTimer->start(interval);
    } else {
        m_autoRefreshTimer->stop();
    }
}

QDateTime NetworkInfo::getLastUpdateTime() const
{
    return m_lastUpdateTime;
}

void NetworkInfo::onAutoRefreshTimer()
{
    refreshAll();
}

void NetworkInfo::onNmcliProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    if (exitCode != 0) {
        emit errorOccurred(QString("nmcli命令执行失败，退出码: %1").arg(exitCode));
        return;
    }
    QString output = QString::fromUtf8(m_nmcliProcess->readAllStandardOutput());
    QMap<QString, DeviceInfo> devMap;
    switch (m_currentCommand) {
    case CommandType::Connections:
        m_cachedConnections = parseConnectionList(output);
        // 继续获取设备列表
        m_currentCommand = CommandType::Devices;
        executeNmcliCommand({"device", "show"});
        break;
    case CommandType::Devices: {
        m_cachedDevices = parseDeviceList(output);
        QMap<QString, DeviceInfo> devMap;
        for (const auto &dev : m_cachedDevices) {
            devMap[dev.name] = dev;
        }
        // merge补全ipAddress
        QStringList devNames;
        for (const auto &dev : m_cachedDevices) devNames << dev.name;
        QMap<QString, QStringList> devIpMap, devMaskMap;
        for (const QString &dev : devNames) {
            QProcess devShowProc;
            devShowProc.start("nmcli", {"device", "show", dev});
            devShowProc.waitForFinished(2000);
            QString devShowOut = QString::fromUtf8(devShowProc.readAllStandardOutput());
            QStringList ips, masks;
            for (const QString &dline : devShowOut.split('\n')) {
                QString tline = dline.trimmed();
                if (tline.startsWith("IP4.ADDRESS[")) {
                    QString ipInfo = tline.section(':', 1).trimmed();
                    QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
                    QRegularExpressionMatch match = ipRegex.match(ipInfo);
                    if (match.hasMatch()) {
                        ips << match.captured(1);
                        int cidr = match.captured(2).toInt();
                        quint32 mask = (cidr >= 0 && cidr <= 32) ? ((0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF) : 0;
                        QString netmask = QString("%1.%2.%3.%4")
                            .arg((mask >> 24) & 0xFF)
                            .arg((mask >> 16) & 0xFF)
                            .arg((mask >> 8) & 0xFF)
                            .arg(mask & 0xFF);
                        masks << netmask;
                    }
                }
            }
            devIpMap[dev] = ips;
            devMaskMap[dev] = masks;
        }
        for (int i = 0; i < m_cachedConnections.size(); ++i) {
            if (devIpMap.contains(m_cachedConnections[i].device)) {
                m_cachedConnections[i].ipAddresses = devIpMap[m_cachedConnections[i].device];
                m_cachedConnections[i].netmasks = devMaskMap[m_cachedConnections[i].device];
            }
            if (!m_cachedConnections[i].ipAddresses.isEmpty()) {
                m_cachedConnections[i].ipAddress = m_cachedConnections[i].ipAddresses[0];
                m_cachedConnections[i].netmask = m_cachedConnections[i].netmasks.value(0);
            }
        }
        m_lastUpdateTime = QDateTime::currentDateTime();
        emit networkInfoUpdated();
        break;
    }
    case CommandType::Stats:
        if (!m_currentDevice.isEmpty()) {
            m_cachedStats[m_currentDevice] = parseDeviceStats(output);
            emit deviceStatsUpdated(m_currentDevice, m_cachedStats[m_currentDevice]);
        }
        break;
    default:
        break;
    }
}

void NetworkInfo::onNmcliProcessError(QProcess::ProcessError error)
{
    QString errorMsg;
    switch (error) {
    case QProcess::FailedToStart:
        errorMsg = "无法启动nmcli命令，请确保NetworkManager已安装";
        break;
    case QProcess::Crashed:
        errorMsg = "nmcli命令异常退出";
        break;
    case QProcess::Timedout:
        errorMsg = "nmcli命令执行超时";
        break;
    default:
        errorMsg = "nmcli命令执行出错";
        break;
    }
    
    emit errorOccurred(errorMsg);
}

QList<ConnectionInfo> NetworkInfo::parseConnectionList(const QString &output)
{
    QList<ConnectionInfo> connections;

    QStringList lines = output.split('\n', Qt::SkipEmptyParts);
    ConnectionInfo currentConn;
    bool inConnection = false;
    
    // 收集所有bond-slave连接，用于过滤原始连接
    QSet<QString> bondSlaveDevices;
    for (const QString &line : lines) {
        QString trimmedLine = line.trimmed();
        if (trimmedLine.startsWith("NAME:")) {
            QString name = trimmedLine.mid(5).trimmed();
            if (name.startsWith("bond-slave-")) {
                // 提取设备名，例如bond-slave-ens37 -> ens37
                QString device = name.mid(11); // 去掉"bond-slave-"前缀
                bondSlaveDevices.insert(device);
            }
        }
    }
    for (const QString &line : lines) {
        QString trimmedLine = line.trimmed();
        

        
        if (trimmedLine.startsWith("NAME:")) {
            if (inConnection && !currentConn.name.isEmpty()) {
                // 检查是否有对应的bond-slave连接，如果有则跳过原始连接
                bool shouldAdd = true;
                if (bondSlaveDevices.contains(currentConn.device)) {
                    // 如果这个设备有对应的bond-slave连接，且当前连接不是bond-slave，则跳过
                    if (!currentConn.name.startsWith("bond-slave-")) {
                        shouldAdd = false;
                    }
                }
                
                if (shouldAdd) {
                currentConn.iconPath = getDeviceIconPath(currentConn.type, currentConn.status);
                connections.append(currentConn);
                }
            }
            currentConn = ConnectionInfo();
            inConnection = true;
            currentConn.name = trimmedLine.mid(5).trimmed();
            // 新增：清空多IP
            currentConn.ipAddresses.clear();
            currentConn.netmasks.clear();
        } else if (inConnection) {
            // 统一小写字段判断
            if (trimmedLine.startsWith("UUID:")) {
                currentConn.uuid = trimmedLine.mid(5).trimmed();
            } else if (trimmedLine.startsWith("DEVICE:")) {
                currentConn.device = trimmedLine.mid(7).trimmed();
                if (m_deviceStatusMap.contains(currentConn.device)) {
                    currentConn.status = m_deviceStatusMap.value(currentConn.device);
                }
            } else if (trimmedLine.startsWith("TYPE:")) {
                QString typeStr = trimmedLine.mid(5).trimmed();
                currentConn.type = parseDeviceType(typeStr);
            } else if (trimmedLine.startsWith("STATE:")) {
                QString stateStr = trimmedLine.mid(6).trimmed();
                if (stateStr.contains("已激活") || stateStr.contains("activated")) {
                    currentConn.status = ConnectionStatus::Connected;
                } else if (stateStr.contains("已断开") || stateStr.contains("disconnected")) {
                    currentConn.status = ConnectionStatus::Disconnected;
                } else if (currentConn.status == ConnectionStatus::Unknown) {
                    currentConn.status = parseConnectionStatus(stateStr);
                }
            } else if (trimmedLine.startsWith("ACTIVE:")) {
                QString activeStr = trimmedLine.mid(7).trimmed();
                currentConn.isActive = (activeStr == "是" || activeStr.toLower() == "yes");
            }
            
            // 特殊处理：从属网卡不应该显示IP地址和DHCP状态
            if (currentConn.name.startsWith("bond-slave-")) {
                // 从属网卡清空IP地址信息
                currentConn.ipAddress.clear();
                currentConn.netmask.clear();
                currentConn.gateway.clear();
                currentConn.dns.clear();
                currentConn.ipAddresses.clear();
                currentConn.netmasks.clear();
                // 从属网卡不显示DHCP状态
                currentConn.dhcp = false;
                currentConn.ipv4Method.clear();
            }
            // DHCP判断兼容大小写
            else if (trimmedLine.toLower().startsWith("ipv4.method:")) {
                QString val = trimmedLine.section(':', 1).trimmed();
                currentConn.ipv4Method = val;
                currentConn.dhcp = (val.toLower() == "auto");
            }
            // 通过DHCP选项判断DHCP状态
            else if (trimmedLine.startsWith("DHCP4.OPTION[")) {
                currentConn.dhcp = true;
            } else if (trimmedLine.toLower().startsWith("ip4.dhcp:")) {
                QString val = trimmedLine.mid(trimmedLine.indexOf(':') + 1).trimmed();
                if (val.toLower() == "yes" || val == "是") currentConn.dhcp = true;
            } else if (trimmedLine.toLower().startsWith("ip4.dhcp.server:")) {
                QString val = trimmedLine.mid(trimmedLine.indexOf(':') + 1).trimmed();
                if (!val.isEmpty()) currentConn.dhcp = true;
            }
            else if (trimmedLine.startsWith("IP4.ADDRESS[")) {
                QString ipInfo = trimmedLine.section(':', 1).trimmed();
                QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
                QRegularExpressionMatch match = ipRegex.match(ipInfo);
                if (match.hasMatch()) {
                    QString ip = match.captured(1);
                    QString mask = cidrToNetmask(match.captured(2));
                    currentConn.ipAddresses << ip;
                    currentConn.netmasks << mask;
                    // 兼容性保留主IP
                    if (currentConn.ipAddress.isEmpty()) {
                        currentConn.ipAddress = ip;
                        currentConn.netmask = mask;
                    }
                }
            } else if (trimmedLine.startsWith("ipv4.addresses")) {
                QString addrStr = trimmedLine.section(':', 1).trimmed();
                if (!addrStr.isEmpty()) {
                    QStringList addrList = addrStr.split(',', Qt::SkipEmptyParts);
                    for (const QString &addr : addrList) {
                        QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
                        QRegularExpressionMatch match = ipRegex.match(addr.trimmed());
                        if (match.hasMatch()) {
                            QString ip = match.captured(1);
                            QString mask = cidrToNetmask(match.captured(2));
                            if (!currentConn.ipAddresses.contains(ip)) {
                                currentConn.ipAddresses << ip;
                                currentConn.netmasks << mask;
                            }
                            if (currentConn.ipAddress.isEmpty()) {
                                currentConn.ipAddress = ip;
                                currentConn.netmask = mask;
                }
                        }
                    }
                }
            }
            else if (trimmedLine.startsWith("IP4.GATEWAY:")) {
                currentConn.gateway = trimmedLine.mid(12).trimmed();
            } else if (trimmedLine.startsWith("IP4.DNS[")) {
                QString dnsVal = trimmedLine.section(':',1).trimmed();
                if (!dnsVal.isEmpty()) {
                    if (!currentConn.dns.isEmpty()) currentConn.dns += " ";
                    currentConn.dns += dnsVal;
                }
            } else if (trimmedLine.startsWith("GENERAL.HWADDR:")) {
                currentConn.macAddress = trimmedLine.mid(15).trimmed();
            } else if (trimmedLine.startsWith("IP6.ADDRESS[1]:")) {
                currentConn.ipv6Address = trimmedLine.mid(15).trimmed();
            } else if (trimmedLine.startsWith("IP6.GATEWAY:")) {
                currentConn.ipv6Gateway = trimmedLine.mid(12).trimmed();
            } else if (trimmedLine.startsWith("IP6.DNS[1]:")) {
                currentConn.ipv6Dns = trimmedLine.mid(11).trimmed();
            } else if (trimmedLine.startsWith("TIMESTAMP-REAL:")) {
                QString timeStr = trimmedLine.mid(15).trimmed();
                QLocale locale(QLocale::Chinese);
                QDateTime dt = locale.toDateTime(timeStr, "yyyy年MM月dd日 dddd HH时mm分ss秒");
                currentConn.activatedAt = dt;
            } else if (trimmedLine.startsWith("IP4.WINS[1]:")) {
                currentConn.wins = trimmedLine.mid(12).trimmed();
            } else if (trimmedLine.startsWith("IP4.NETBIOS:")) {
                QString val = trimmedLine.mid(12).trimmed().toLower();
                currentConn.netbios = (val == "yes" || val == "是");
            }
        }
    }
    if (inConnection && !currentConn.name.isEmpty()) {
        currentConn.iconPath = getDeviceIconPath(currentConn.type, currentConn.status);
        connections.append(currentConn);
    }
    // 补全：如果连接没有IP，尝试用设备信息补全
    for (ConnectionInfo &conn : connections) {
        if (conn.ipAddress.isEmpty() && !conn.device.isEmpty()) {
            for (const DeviceInfo &dev : m_cachedDevices) {
                if (dev.name == conn.device && !dev.ipAddress.isEmpty()) {
                    conn.ipAddress = dev.ipAddress;
                    conn.netmask = dev.netmask;
                    break;
                }
            }
        }
    }
    return connections;
}

QList<DeviceInfo> NetworkInfo::parseDeviceList(const QString &output)
{
    QList<DeviceInfo> devices;
    QStringList lines = output.split('\n', Qt::SkipEmptyParts);
    DeviceInfo currentDevice;
    bool inDevice = false;
    QStringList dnsList;
    QStringList ipv6DnsList;
    for (const QString &line : lines) {
        QString trimmedLine = line.trimmed();
        if (trimmedLine.startsWith("GENERAL.DEVICE:")) {
            if (inDevice && !currentDevice.name.isEmpty()) {
                currentDevice.dns = dnsList.join(" ");
                currentDevice.ipv6Dns = ipv6DnsList.join(" ");
                currentDevice.model = "";
                devices.append(currentDevice);
            }
            currentDevice = DeviceInfo();
            dnsList.clear();
            ipv6DnsList.clear();
            inDevice = true;
            currentDevice.name = trimmedLine.mid(15).trimmed();
        }
        if (trimmedLine.startsWith("IP4.DNS[")) {
            dnsList << trimmedLine.section(':',1).trimmed();
        }
        if (trimmedLine.startsWith("IP6.DNS[")) {
            ipv6DnsList << trimmedLine.section(':',1).trimmed();
        }
            if (trimmedLine.startsWith("GENERAL.TYPE:")) {
                QString typeStr = trimmedLine.mid(13).trimmed();
                currentDevice.type = parseDeviceType(typeStr);
            } else if (trimmedLine.startsWith("GENERAL.STATE:")) {
                QString stateStr = trimmedLine.mid(14).trimmed();
                currentDevice.isEnabled = (stateStr != "unavailable");
            } else if (trimmedLine.startsWith("GENERAL.HWADDR:")) {
                currentDevice.macAddress = trimmedLine.mid(15).trimmed();
            } else if (trimmedLine.startsWith("GENERAL.DRIVER:")) {
                currentDevice.driver = trimmedLine.mid(15).trimmed();
            } else if (trimmedLine.startsWith("GENERAL.FIRMWARE-VERSION:")) {
                currentDevice.firmware = trimmedLine.mid(24).trimmed();
        } else if (trimmedLine.startsWith("GENERAL.SPEED:")) {
            currentDevice.speed = trimmedLine.mid(14).trimmed();
        } else if (trimmedLine.startsWith("CAPABILITIES.SPEED:")) {
            currentDevice.speed = trimmedLine.mid(19).trimmed();
        } else if (trimmedLine.startsWith("GENERAL.STATE:")) {
            currentDevice.state = trimmedLine.mid(14).trimmed();
        } else if (trimmedLine.startsWith("IP4.ADDRESS[1]:")) {
            QString ipInfo = trimmedLine.mid(15).trimmed();
            QRegularExpression ipRegex(R"((\d+\.\d+\.\d+\.\d+)/(\d+))");
            QRegularExpressionMatch match = ipRegex.match(ipInfo);
            if (match.hasMatch()) {
                currentDevice.ipAddress = match.captured(1);
                currentDevice.netmask = cidrToNetmask(match.captured(2));
            }
        } else if (trimmedLine.startsWith("IP6.ADDRESS[1]:")) {
            currentDevice.ipv6Address = trimmedLine.mid(15).trimmed();
        } else if (trimmedLine.startsWith("IP4.GATEWAY:")) {
            currentDevice.gateway = trimmedLine.mid(12).trimmed();
        } else if (trimmedLine.startsWith("IP6.GATEWAY:")) {
            currentDevice.ipv6Gateway = trimmedLine.mid(12).trimmed();
        } else if (trimmedLine.startsWith("IP4.DHCP:")) {
            QString val = trimmedLine.mid(9).trimmed();
        } else if (trimmedLine.startsWith("IP4.DHCP.SERVER:")) {
            QString val = trimmedLine.mid(16).trimmed();
        }
    }
    if (inDevice && !currentDevice.name.isEmpty()) {
        currentDevice.dns = dnsList.join(" ");
        currentDevice.ipv6Dns = ipv6DnsList.join(" ");
        currentDevice.model = "";
        devices.append(currentDevice);
    }
    return devices;
}

NetworkStats NetworkInfo::parseDeviceStats(const QString &output)
{
    NetworkStats stats = {0, 0, 0, 0, 0, 0};
    QStringList lines = output.split('\n', Qt::SkipEmptyParts);
    
    for (const QString &line : lines) {
        QString trimmedLine = line.trimmed();
        
        if (trimmedLine.startsWith("GENERAL.STATS.RX_BYTES:")) {
            stats.bytesReceived = trimmedLine.mid(23).trimmed().toLongLong();
        } else if (trimmedLine.startsWith("GENERAL.STATS.TX_BYTES:")) {
            stats.bytesSent = trimmedLine.mid(23).trimmed().toLongLong();
        } else if (trimmedLine.startsWith("GENERAL.STATS.RX_PACKETS:")) {
            stats.packetsReceived = trimmedLine.mid(25).trimmed().toLongLong();
        } else if (trimmedLine.startsWith("GENERAL.STATS.TX_PACKETS:")) {
            stats.packetsSent = trimmedLine.mid(25).trimmed().toLongLong();
        } else if (trimmedLine.startsWith("GENERAL.STATS.RX_ERRORS:")) {
            stats.errorsReceived = trimmedLine.mid(25).trimmed().toLongLong();
        } else if (trimmedLine.startsWith("GENERAL.STATS.TX_ERRORS:")) {
            stats.errorsSent = trimmedLine.mid(25).trimmed().toLongLong();
        }
    }
    
    return stats;
}

void NetworkInfo::executeNmcliCommand(const QStringList &args)
{
    QProcess proc;
    proc.start("nmcli", args);
    bool finished = proc.waitForFinished(3000);
    QString output = QString::fromUtf8(proc.readAllStandardOutput());
    if (!finished) {
        return;
    }
    // 直接在这里解析
    switch (m_currentCommand) {
    case CommandType::Connections:
        m_cachedConnections = parseConnectionList(output);
        // 继续获取设备列表
        m_currentCommand = CommandType::Devices;
        executeNmcliCommand({"device", "show"});
        break;
    case CommandType::Devices:
        m_cachedDevices = parseDeviceList(output);
        m_lastUpdateTime = QDateTime::currentDateTime();
        emit networkInfoUpdated();
        break;
    case CommandType::Stats:
        if (!m_currentDevice.isEmpty()) {
            m_cachedStats[m_currentDevice] = parseDeviceStats(output);
        }
        break;
    default:
        break;
    }
}

ConnectionStatus NetworkInfo::parseConnectionStatus(const QString &status)
{
    QString s = status.toLower();
    if (s.contains("connected") || s.contains("activated") || s.contains("已连接")) {
        return ConnectionStatus::Connected;
    } else if (s.contains("disconnected") || s.contains("deactivated") || s.contains("已断开")) {
        return ConnectionStatus::Disconnected;
    } else if (s.contains("connecting") || s.contains("activating") || s.contains("连接中")) {
        return ConnectionStatus::Connecting;
    } else if (s.contains("disconnecting") || s.contains("deactivating") || s.contains("断开中")) {
        return ConnectionStatus::Disconnecting;
    }
    return ConnectionStatus::Unknown;
}

DeviceType NetworkInfo::parseDeviceType(const QString &type)
{
    QString lowerType = type.toLower();
    if (lowerType == "ethernet" || lowerType == "802-3-ethernet") {
        return DeviceType::Ethernet;
    } else if (lowerType == "wifi" || lowerType == "802-11-wireless") {
        return DeviceType::WiFi;
    } else if (lowerType == "loopback") {
        return DeviceType::Loopback;
    } else if (lowerType == "bridge") {
        return DeviceType::Bridge;
    } else if (lowerType == "bond") {
        return DeviceType::Bond;
    } else if (lowerType == "vlan") {
        return DeviceType::Vlan;
    }
    return DeviceType::Unknown;
}

QString NetworkInfo::getDeviceIconPath(DeviceType type, ConnectionStatus status)
{
    QString iconName;
    switch (type) {
    case DeviceType::Ethernet:
        iconName = (status == ConnectionStatus::Connected) ? "net_connected.png" : "net_disconnected.png";
        break;
    case DeviceType::WiFi:
        iconName = (status == ConnectionStatus::Connected) ? "wifi_connected.png" : "wifi_disconnected.png";
        break;
    default:
        iconName = (status == ConnectionStatus::Connected) ? "net_connected.png" : "net_disconnected.png";
        break;
    }
    return QString(":/icons/resources/%1").arg(iconName);
}

void NetworkInfo::updateDeviceStatusMap(const QString &output)
{
    m_deviceStatusMap.clear();
    QStringList lines = output.split('\n', Qt::SkipEmptyParts);
    // 跳过表头
    for (int i = 1; i < lines.size(); ++i) {
        QString line = lines[i].trimmed();
        if (line.isEmpty()) continue;
        // 用正则提取四列（DEVICE TYPE STATE CONNECTION）
        QRegularExpression re(R"(^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+(.+)$)");
        QRegularExpressionMatch match = re.match(line);
        if (!match.hasMatch()) continue;
        QString device = match.captured(1);
        QString state = match.captured(3);
        ConnectionStatus status = parseConnectionStatus(state);
        m_deviceStatusMap[device] = status;
    }
}

// 互联网连通性检测（同步ping，实际可用异步优化）
void NetworkInfo::updateInternetConnectivity() {
    for (ConnectionInfo &conn : m_cachedConnections) {
        if (!conn.ipAddress.isEmpty()) {
            conn.hasInternet = checkInternetConnectivity(conn.ipAddress);
        } else {
            conn.hasInternet = false;
        }
    }
}

bool NetworkInfo::checkInternetConnectivity(const QString &ip) {
    QProcess pingProc;
    // 只ping一次，超时1秒
    QStringList args = {"-c", "1", "-W", "1", "8.8.8.8"};
    int exitCode = -1;
    pingProc.start("ping", args);
    if (pingProc.waitForFinished(1500)) {
        exitCode = pingProc.exitCode();
    }
    return exitCode == 0;
}

QString NetworkInfo::getConnectionDuration(const ConnectionInfo &conn) {
    if (!conn.activatedAt.isValid()) return "--:--:--";
    qint64 secs = conn.activatedAt.secsTo(QDateTime::currentDateTime());
    int h = secs / 3600;
    int m = (secs % 3600) / 60;
    int s = secs % 60;
    return QString("%1:%2:%3").arg(h,2,10,QChar('0')).arg(m,2,10,QChar('0')).arg(s,2,10,QChar('0'));
}

QString NetworkInfo::getSpeedString(const QString &speedStr) {
    bool ok = false;
    int speed = speedStr.toInt(&ok);
    if (!ok || speed <= 0) return "-";
    if (speed >= 1000) {
        double gbps = speed / 1000.0;
        return QString::number(gbps, 'f', 1) + " Gbps";
    } else {
        return QString::number(speed) + " Mbps";
    }
}

// 新增：用nmcli networking connectivity检测全局互联网连通性
void NetworkInfo::updateInternetConnectivityFromNmcli() {
    QProcess proc;
    proc.start("nmcli", {"networking", "connectivity"});
    proc.waitForFinished(1500);
    QString result = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
    bool hasInternet = (result == "full");
    for (ConnectionInfo &conn : m_cachedConnections) {
        conn.hasInternet = hasInternet && conn.isActive;
    }
}

QString NetworkInfo::getDHCPStatusByDevice(const QString &deviceName) {
    // 1. 获取当前设备对应的 connection profile 名
    QProcess proc;
    proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << deviceName);
    proc.waitForFinished();
    QString profileName = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
    if (profileName.isEmpty() || profileName == "--") {
        return QStringLiteral("未知");
    }
    // 2. 用 profile 名查 connection 详情
    QProcess proc2;
    proc2.start("nmcli", QStringList() << "connection" << "show" << profileName);
    proc2.waitForFinished();
    QString output = QString::fromUtf8(proc2.readAllStandardOutput());
    QRegExp rx("ipv4\\.method:\\s*(\\w+)");
    if (rx.indexIn(output) != -1) {
        QString method = rx.cap(1);
        return (method == "auto") ? QStringLiteral("已启用") : QStringLiteral("未启用");
    }
    return QStringLiteral("未知");
}

NetworkStats NetworkInfo::getDeviceStatsFromProc(const QString &deviceName)
{
    NetworkStats stats = {0, 0, 0, 0, 0, 0};
    QFile file("/proc/net/dev");
    bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if (!openOk)
        return stats;
    QByteArray allData = file.readAll();
    QString allText = QString::fromUtf8(allData);
    QStringList lines = allText.split('\n', Qt::SkipEmptyParts);
    for (const QString &line : lines) {
        if (line.contains(deviceName + ":")) {
            QStringList parts = line.split(QRegExp("[ :]+"), Qt::SkipEmptyParts);
            if (parts.size() >= 10) {
                stats.bytesReceived = parts[1].toLongLong();
                stats.bytesSent = parts[9].toLongLong();
            }
            break;
        }
    }
    return stats;
}

#include "moc_networkinfo.cpp"